﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using System.Net;

namespace SynoManager.DownloadStation.Plugins
{
    [DownloadStationPlugin("Clipboard Listener", "Watches the clipboard for (downloadable) urls", "SynoManager Team", "1.0")]
    public class ClipboardListenerPlugin : IDownloadStationPlugin
    {
        private DownloadStationService service;
        private ClipboardWatcher watcher = new ClipboardWatcher();
        private bool enabled = Properties.Settings.Default.EnableClipboardListener;

        public bool Enabled
        {
            get { return enabled; }
            set
            {
                bool change = (enabled != value);
                enabled = value;
                Properties.Settings.Default.EnableClipboardListener = value;
                
                if (change)
                {
                    if (enabled)
                        Start();
                    else
                        Stop();
                }
            }
        }

        public void Initialize(DownloadStationService service)
        {
            this.service = service;
            watcher.NewData += new ClipboardEventHandler(watcher_NewData);
            if (enabled)
                Start();
        }

        void watcher_NewData(object sender, ClipboardEventArgs args)
        {
            if (service.Plugin == null)
                return; // Not initialized, so we can stop right here. This happens when the clipboard contains text when the application is started

            if (isDownloadableUrl(args.Text))
            {
                lastUrl = args.Text;
                service.Plugin.Host.NotifyIcon.ShowBalloonTip(3000, "SynoManager Clipboard Watcher", "Click here to download the following URL:\n"+args.Text, ToolTipIcon.Info, downloadClipText);
            }
        }

        public bool isDownloadableUrl(string url)
        {
            Uri uri;
            if (!Uri.TryCreate(url, UriKind.Absolute, out uri))
                return false;
            try {

            HttpWebRequest request = WebRequest.Create(uri) as HttpWebRequest;

            // A file:// url is technically a url, but we can't use it. WebRequest.Create will create a FileWebRequest
            if (request == null)
                return false;

            // We just want to know the headers
            request.Method = "HEAD";

            HttpWebResponse response = (HttpWebResponse) request.GetResponse();

            string contentType = response.ContentType;

            // sometimes contentType contains a ;, remove additional encoding information
            if (contentType.IndexOf(';') > 0)
            {
                contentType = contentType.Substring(0, contentType.IndexOf(';'));
            }

            // everything but text/html is downloadable I think :)
            // TODO: refactor this to create a 'whitelist'
            return (contentType != "text/html");
           } catch (WebException)
           {
               // something went wrong, so we assume it's an invalid url
               return false;
           }
        }

        private string lastUrl;

        private void downloadClipText(object sender, EventArgs e)
        {
            service.AddUrl(lastUrl);
        }

        public void Close()
        {
            Stop();
        }

        private void Start()
        {
            watcher.RegisterClipboardViewer();
        }

        private void Stop()
        {
            watcher.UnregisterClipboardViewer();
        }
    }
}
